<?php
namespace xg\log;
use xg\interfaces\Log as LogInterface;
use \helper\File as FileHelper;
use \helper\Arr;

class File implements LogInterface {
	protected $config=[];
	protected $level=[];
	protected $file=null;
	protected $path=null;
	protected $logs=[];
	//修改数据库配置
	public function config($name,$value=null){
		if(is_array($name)){
			$this->config=Arr::extend($this->config,$name);
		}elseif($name and is_string($name)){
			$this->config[$name]=$value;
		}
		if($this->config['level']){
			$this->level=Arr::split($this->config['level']);
		}else{
			$this->level=[];
		}
		if($this->config['path']){
			$this->path=$this->config['path'];
		}else{
			$this->path='xg:runtime/log/';
		}
		if($this->config['file']){
			$this->file=$this->config['file'];
		}else{
			$this->file=null;
		}
		return $this;
	}
	//记录日志
	public function log($info){
		if(
			$info and in_array($info['level'],$this->level)
			or (
				$this->level[$info['level']]
				and in_array($info['type'],Arr::split($this->level[$info['level']]))
			)
		){
			$this->logs[]=$info;
		}
	}
	//手动保存日志
	public function save(){
		$data=[];
		foreach($this->logs as $log){
			if($log and $info=$this->format($log)){
				$data[]=$info;
			}
		}
		if($data){
			$file=$this->getFile();
			mkdir(dirname($file),0755,true);
			$logstr=Arr::join($data,PHP_EOL);
			$logstr.=str_repeat(PHP_EOL,20);
			file_put_contents($file,$logstr,FILE_APPEND);
		}
	}
	public function write($info){
		if(
			$info and in_array($info['level'],$this->level)
			or (
				$this->level[$info['level']]
				and in_array($info['type'],Arr::split($this->level[$info['level']]))
			)
		){
			$info=$this->format($info);
			if($info){
				$file=$this->getFile();
				mkdir(dirname($file),0755,true);
				file_put_contents($file,$info,FILE_APPEND);
			}
		}
	}

	//获取保存文件
	protected function getFile(){
		if($this->config['file']){
			return $this->config['file'];
		}
		$file=FileHelper::path($this->path,date('Ymd').'.log');
		$this->checkSize($file);
		$this->checkMax();
		return $file;
	}
	//检测文件大小
	protected function checkSize($file){
		if($this->config['file_size'] and is_file($file) and $this->config['file_size']<=filesize($file)){
			$name=substr(basename($file),0,-4);
			$newName=FileHelper::path(dirname($file),$name.'-'.time().'.log');
			try{
				rename($file,$newName);
			}catch(\Exception $e){
				
			}
		}
	}
	//检测最大文件数
	protected function checkMax(){
		if($this->config['max_files']){
			$files=FileHelper::findFiles($this->path,'log');
			$count=count($files);
			if($count>$this->config['max_files']){
				//统计文件创建时间
				$timeData=[];
				foreach($files as $file){
					$timeData[$file]=filectime($file);
				}
				asort($timeData);//排序
				//删除创建时间靠前的文件
				while($count>$this->config['max_files']){
					$count--;
					try{
						unlink(array_shift($timeData));
					}catch(\Exception $e){
						
					}
				}
			}
		}
	}
	//生成单条记录信息
	protected function format($info){
		if(!$info['info']){
			return null;
		}
		if($info['time']){
			$time=$info['time'];
		}else{
			$time=microtime(true);
		}
		list($sec,$msec)=Arr::split($time,'.');
		$time='['.date('Y-m-d H:i:s',$sec).($msec?'.'.$msec:'').']';
		if(is_array($info['info']) or is_object($info['info'])){
			switch($this->config['encoding']){
				case 'json':
					$loginfo=json_encode($info['info'],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
					break;
				case 'serialize':
					$loginfo=serialize($info['info']);
					break;
				default:
					$loginfo=print_r($info['info'],true);
					break;
			}
		}else{
			$loginfo=$info['info'];
		}
		if($info['level']){
			$level='['.$info['level'].']';
		}else{
			$level='[info]';
		}
		if($info['type']){
			$type='['.$info['type'].']';
		}else{
			$type='[info]';
		}
		return Arr::join([$time,$level,$type,$loginfo],' ');
	}
}
?>